package com.ccg.service;

import com.ccg.dao.OrderDao;
import com.ccg.entity.Message;
import com.ccg.entity.Order;
import com.ccg.entity.Order_Room;
import com.ccg.entity.User;
import com.ccg.utils.DateUtil;
import com.ccg.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private Order_RoomService order_roomService;
    @Autowired
    Date_Rt_NumberService date_rt_numberService;
    @Autowired
    RoomService roomService;
    @Autowired
    RoomTypeService roomTypeService;

    //用户订房下订单的逻辑
    //订单添加,添加订单的房间
    @Transactional
    public Message addOrderByU_id(Order order) throws ParseException {
        //获取预订房间数量
        order.setRoomNumber(order.getOrder_Rooms().size());
        //计算该订单所需预付的费用
        double orderMoney = 0, roomMoney;
        //获取预订的房间数量
        for (Order_Room or : order.getOrder_Rooms()) {
            //预订的该房间类型的天数
            int days = DateUtil.timeFormat(or.getOut_date()).compareTo(DateUtil.timeFormat(or.getIn_date()))+1;
            roomMoney = roomTypeService.getRoomTypeByRt_Id(or.getRt_id()).getPrice()*days;
            orderMoney += roomMoney;
        }
        order.setOrderMoney(orderMoney);
        //插入订单,并判断是否成功
        if (orderDao.addOrderByU_id(order) == 1) {
            for (Order_Room order_room : order.getOrder_Rooms()) {
                //入住日期不能在退房日期之后
                if (DateUtil.timeFormat(order_room.getOut_date()).before(DateUtil.timeFormat(order_room.getIn_date()))) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return new Message(1, "预定失败", "入住日期不能在退房日期之后");
                }
                order_room.setOrder_id(order.getOrder_id());
                //当订单插入房间类型失败抛出异常,回滚事务
                if (order_roomService.addOrderRoom(order_room) == 0) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return new Message(1, "预定失败", "异常");
                }
            }
            return new Message(0, "预定成功", null);
        }
        return new Message(1, "预定失败", "异常");
    }

    //用户查看自己的所有订单
    public List<Order> findOrderByName(int u_id) {
        return orderDao.findOrderByName(u_id);
    }

    //管理员查询用户的所有订单
    public List<Order> adminGetUserOrders(int u_id) {
        List<Order> orders = orderDao.adminGetUserOrders(u_id);
        for (Order order : orders) {
            order.setOrder_Rooms(order_roomService.findAllOrderRoom(order.getOrder_id()));
        }
        return orders;
    }

    //管理员根据订单状态查找订单
    public List<Order> findOrderByStatus(int orderStatus) {
        return orderDao.findOrderByStatus(orderStatus);
    }

    //根据order_id查找一个订单
    public Order findOrderByOrderId(int order_id) {
        return orderDao.findOrderByOrderId(order_id);
    }

    //用户取消订单,只能直接取消未被审核的的订单
    public Message orderCancelByUser(Order order) {
        int i = orderDao.orderCancelByUser(order);
        if (i == 1) return new Message(0, "取消订单成功", null);
        else return new Message(1, "取消订单失败", null);
    }

    //用户删除订单,只能删除已完成的或被用户取消的订单
    public int deleteOrder(Order order) {
        return orderDao.deleteOrder(order);
    }

    //酒店审核处理用户预订的订单
    //需要order_id以及orderStatus两个参数
    @Transactional
    public Message checkUserOrder(Order order) {
        //判断是拒绝还是通过,如果是酒店拒绝
        if (order.getOrderStatus() == -2) {
            orderDao.orderCancelByHotel(order);
            return new Message(0, "拒绝该订单成功", null);
        }
        //酒店通过,进行接下来一系列的判断
        if (orderDao.orderSuccessByHotel(order.getOrder_id()) != 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Message(1, "订单通过失败", "该订单可能被用户取消");
        }
        //获取该订单的订单房间数据
        List<Order_Room> lists = order_roomService.findAllOrderRoom(order.getOrder_id());
        if (lists.size() == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Message(1, "订单通过失败", "该订单没有订房");
        }
        //将该订单的房间类型预定日期的库存更新
        for (Order_Room or : lists) {
            //用户订房间库存减一,用order_id属性传参
            or.setOrder_id(-1);
            //判断更新库存是否存在需要的房间类型资源
            if (date_rt_numberService.updateNumberByDateRt_id(or) < 1) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return new Message(1, "订单通过失败", "可能没有相关的房间资源");
            }
        }
        //判断是否有足够的库存安排给该订单
        if (date_rt_numberService.findBad() >= 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Message(1, "订单通过失败", "该日期没有足够的房间安排给该订单");
        } else return new Message(0, "订单通过成功", null);
    }

    //用户到达前台办理入住处理逻辑
    //安排房间以及相关的信息录入
    //参数：订单主体信息、以及与之关联的订单房间信息
    @Transactional
    public Message userInHotel(Order order) {
        //设置该订单为入住状态并判断是否成功
        if (orderDao.orderUserArrive(order.getOrder_id()) == 1) {
            //List<Order_Room> lists = order_roomService.findAllOrderRoom(order.getOrder_id());
            //获取该订单的所都订单房间
            List<Order_Room> lists = order.getOrder_Rooms();
            for (Order_Room or : lists) {
                //安排一个房间并判断是否成功
                //并将被安排的房间设置为已入住状态
                //成功返回1,失败返回0
                if (order_roomService.addRoomToOrder(or) != 1) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return new Message(1, "安排房间异常", null);
                }
            }
            return new Message(0, "安排房间入住成功", null);
        } else {
            //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Message(1, "异常错误", null);
        }
    }

    //用户到达前台办理订单退房逻辑
    //参数:order_id
    @Transactional
    public Message orderComplete(Order order) throws ParseException {
        //设置该房间状态为订单完成状态,并判断是否成功
        if (orderDao.orderCompleteByHotel(order.getOrder_id()) == 1) {
            //获取该订单所有房间
            //计算订单实际消费金额
            double realMoney=0;
            List<Order_Room> lists = order_roomService.findAllOrderRoom(order.getOrder_id());
            for (Order_Room or : lists) {
                //结束一个房间的使用,以及相关的逻辑处理,成功返回1,失败返回0需回滚事务
                if (order_roomService.outRoom(or) != 1) {
                    return new Message(1, "结束房间异常", or.getRoom_id() + "房间结束异常");
                }
                Date realOutDate;
                if(or.getReal_out_date()==null||or.getReal_out_date()=="")
                    realOutDate = new Date();
                else realOutDate = DateUtil.timeFormat(or.getReal_out_date());
                int days = realOutDate.compareTo(DateUtil.timeFormat(or.getReal_in_date()));
                realMoney += roomTypeService.getRoomTypeByRt_Id(or.getRt_id()).getPrice()*days;
            }
            //更新订单实际消费金额
            order.setRealMoney(realMoney);
            if(orderDao.updateRealMoney(order)!=1)
                return new Message(1, "结束订单异常","计算订单实际消费金额异常");

            return new Message(0, "结束订单成功", "订单完成");
        } else {
            //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new Message(1, "异常错误", "结束订单异常");
        }
    }

    //订单统计功能
    //分页获取最近day天的订单
    public PageBean<Order> beforeDaysOrder(int currPage,String startDate,String endDate){
        HashMap<String, Object> map = new HashMap<>();//哈希集合存储不重复的数据
        map.put("startDate",startDate);
        map.put("endDate",endDate);
        PageBean<Order> pageBean = new PageBean<>();
        //每页显示的数据
        int pageSize = 10;
        pageBean.setPageSize(pageSize);

        //封装总记录数
        int totalCount = orderDao.getBeforeDayOrderCount(map);
        pageBean.setTotalCount(totalCount);
        //如果没有数据,直接返回
        if(totalCount==0){
            return pageBean;
        }
        //封装总页数
        double tc = totalCount;
        Double num = Math.ceil(tc / pageSize);//向上取整
        pageBean.setTotalPage(num.intValue());

        //传入的当前页小于1时则等于1，大于总页数则等于总页数也就是最后一页
        if(currPage<1) currPage=1;
        else if(currPage>pageBean.getTotalPage()) currPage = pageBean.getTotalPage();
        //封装当前页数
        pageBean.setCurrPage(currPage);
        map.put("start", (currPage - 1) * pageSize);
        map.put("size", pageBean.getPageSize());
        //封装每页显示的数据
        List<Order> lists = orderDao.beforeDaysOrder(map);
        pageBean.setLists(lists);

        return pageBean;
    }
    //分页获取两个日期之间的订单数量
    public int getOrdersInDate(HashMap<String, Object> map){
        return orderDao.getBeforeDayOrderCount(map);
    }
    //获取最近day天的销售金额
    public int getAllMoney(HashMap<String, Object> map){
        int[] moneys = orderDao.getAllMoney(map);
        int totalMoney=0;
        for(int money:moneys){
            totalMoney+=money;
        }
        return totalMoney;
    }

}
